#pragma once

#include <unordered_map>
#include "localcommon.hpp"
#include "localepoller.hpp"
#include "localconnection.hpp"

namespace Local_Reactor
{
    class Reactor
    {
        static const int _maxnum = 128;

    private:
        /**********检测函数************** */
        bool IsConnectionExists(const std::shared_ptr<Local_Connection::LocalConnection> &conn)
        {
            auto ret_fin = _connections.find(conn->GetFd());
            if (ret_fin == _connections.end())
                return false;
            else
                return true;
        }
        bool IsConnectionExists(int sockfd)
        {
            auto ret_fin = _connections.find(sockfd);
            if (ret_fin == _connections.end())
                return false;
            else
                return true;
        }
        bool IsConnectionEmpty()
        {
            return _connections.empty();
        }

    public:
        /**********构造析构************** */
        Reactor()
            : _epoller_ptr(std::make_unique<Local_Epoller::LocalEpoller>()),
              _isrunning(false)
        {
        }
        ~Reactor() {}
        /**********成员函数************** */
        void Start()
        {
            if (IsConnectionEmpty())
                return;
            _isrunning = true;
            int lo_timeout = -1;
            while (_isrunning)
            {
                int ret_epo = _epoller_ptr->WaitEvent(_revs, _maxnum, lo_timeout);
                for (int i = 0; i < _maxnum; i++)
                {
                    int lo_fd = _revs[i].data.fd;
                    int lo_event = _revs[i].events;
                    // 1.将所有的异常处理转换为IO错误
                    if (lo_event & EPOLLERR)
                        lo_event |= (EPOLLIN | EPOLLOUT);
                    if (lo_event & EPOLLHUP)
                        lo_event |= (EPOLLIN | EPOLLOUT);
                    // 2.将所有的异常处理转换为一个函数
                    // Local_Connection::LocalConnection::Excepter()

                    if (lo_event & EPOLLIN)
                    {
                        // 去除重复fd

                        if (IsConnectionExists(lo_fd))
                            _connections[lo_fd]->Recver();
                    }
                    if (lo_event & EPOLLOUT)
                    {
                        // 去除重复fd
                        if (IsConnectionExists(lo_fd))
                            _connections[lo_fd]->Sender();
                    }
                }
            }
            _isrunning = false;
        }
        // 该接口要把所有的新连接添加到_connections，并且，写透到epoll内核中！！！！！
        void AddConnection(std::shared_ptr<Local_Connection::LocalConnection> &conn)
        {
            // 检测是否重复添加 connection 链接 exists 存在
            if (IsConnectionExists(conn))
            {
                Local_Log::LOG(Local_Log::LogLever::LWARNING) << "connection is exists " << conn->GetFd();
                return;
            }

            // 1. conn对应的fd和他要关心的事件，写透到内核中！
            uint32_t lo_events = conn->GetEvent();
            int lo_sockfd = conn->GetFd();
            _epoller_ptr->AddEvent(lo_sockfd, lo_events);

            // 2.设置当前conn的拥有者回指指针
            conn->SetReactor(this);

            // 3. 将具体的connection添加到_connections
            _connections[lo_sockfd] = conn;
            Local_Log::LOG(Local_Log::LogLever::LINFO) << "AddConnection success " << conn->GetFd();
        }
        void Stop()
        {
            _isrunning = false;
        }

    private:
        // 1.epoll模型
        std::unique_ptr<Local_Epoller::LocalEpoller> _epoller_ptr;
        // 2.启动标志位
        bool _isrunning;
        // 3.fd : LocalConnection
        std::unordered_map<int, std::shared_ptr<Local_Connection::LocalConnection>> _connections;
        // 4.
        struct epoll_event _revs[_maxnum];
    };
}